{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 分类训练"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "   * 将文件打包 把2打包成字节，高位"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "b'\\x02'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import struct\n",
    "struct.pack('B',2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2051, 60000, 28, 28)\n",
      "47040000\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "IOPub data rate exceeded.\n",
      "The notebook server will temporarily stop sending output\n",
      "to the client in order to avoid crashing it.\n",
      "To change this limit, set the config variable\n",
      "`--NotebookApp.iopub_data_rate_limit`.\n",
      "\n",
      "Current values:\n",
      "NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n",
      "NotebookApp.rate_limit_window=3.0 (secs)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import struct\n",
    "with open('./MNIST_data/train-images-idx3-ubyte','rb') as f1:\n",
    "    buffer = f1.read(4*4) # 读取4个int类型\n",
    "    head = struct.unpack('>iiii',buffer) # 根据解压解压出4个int\n",
    "    print(head)\n",
    "    length = head[1]*head[2]*head[3] # 解压 60000, 28, 28\n",
    "    print(length)\n",
    "    buffer = f1.read(length)\n",
    "    print(buffer)\n",
    "    data = struct.unpack('>{}B'.format(length),buffer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "47040000"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(data) # 输出长度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "imgs = np.reshape(data,(head[1],head[2],head[3])) # 重新塑性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 28, 28)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "imgs.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示5张图片，0-255 级灰度\n",
    "import matplotlib.pyplot as plt\n",
    "for i in range(5):\n",
    "    plt.imshow(imgs[i], cmap = 'gray')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\feature_extraction\\text.py:17: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working\n",
      "  from collections import Mapping, defaultdict\n"
     ]
    }
   ],
   "source": [
    "from sklearn.datasets import fetch_mldata\n",
    "mnist = fetch_mldata('MNIST original', data_home='./')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'DESCR': 'mldata.org dataset: mnist-original',\n",
       " 'COL_NAMES': ['label', 'data'],\n",
       " 'target': array([0., 0., 0., ..., 9., 9., 9.]),\n",
       " 'data': array([[0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        ...,\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0],\n",
       "        [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mnist"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "X, y = mnist['data'], mnist['target']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(70000, 784)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(70000,)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "some_digit = X[36000]\n",
    "some_digit_image = some_digit.reshape(28,28)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.imshow(some_digit_image,cmap = matplotlib.cm.binary)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y[36000]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 建立测试集和训练集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train,X_test,y_train,y_test = X[:60000],X[60000:],y[:60000],y[60000:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([48388, 38849, 52119, ..., 20988, 52205, 25564])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将数据集合交叉洗牌，交叉验证时，每个子集合数据分布均匀，有些机器学习算法对训练实例的顺序敏感\n",
    "import numpy as np\n",
    "shuffle_index = np.random.permutation(60000)\n",
    "shuffle_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       ...,\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0],\n",
       "       [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#    * 实例\n",
    "### 训练一个二元分类器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False, False, False, ..., False, False, False])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 识别数字5 ，二元分类5或者非5\n",
    "# 创建目标向量\n",
    "y_train_5 = (y_train == 5)\n",
    "y_train_5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False, False, ..., False, False, False],\n",
       "       [ True, False,  True, ..., False,  True, False],\n",
       "       [False, False,  True, ..., False,  True, False],\n",
       "       ...,\n",
       "       [False, False, False, ..., False, False, False],\n",
       "       [False,  True, False, ..., False, False, False],\n",
       "       [False, False, False, ..., False, False, False]])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_5.reshape(20, -1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_test_5 = (y_test == 5) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SGD主要应用在大规模稀疏数据问题上，经常用在文本分类及自然语言处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([ True])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# SGD 梯度下降 分类器， 适合非常大的数据集，独立处理训练集数据，一次一个，适合在线学习，\n",
    "# SGD主要应用在大规模稀疏数据问题上，经常用在文本分类及自然语言处理\n",
    "from sklearn.linear_model import SGDClassifier\n",
    "sgd_clf = SGDClassifier(random_state = 42)\n",
    "sgd_clf.fit(X_train,y_train_5)\n",
    "\n",
    "sgd_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.性能考核\n",
    "### 使用交叉验证测量精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.957  , 0.94795, 0.96385])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 评估分类器比评估回归器要困难得多\n",
    "\n",
    "# 3个折叠，正确率达到 95% 以上\n",
    "from sklearn.model_selection import cross_val_score\n",
    "cross_val_score(sgd_clf,X_train,y_train_5, cv=3,scoring = \"accuracy\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 每张图都分类成 非5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.base import BaseEstimator\n",
    "class Never5Classifier(BaseEstimator):\n",
    "    def fit(self,X,y=None):\n",
    "        pass\n",
    "    def predict(self,X):\n",
    "        return np.zeros((len(X),1),dtype=bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False],\n",
       "       [False],\n",
       "       [False],\n",
       "       ...,\n",
       "       [False],\n",
       "       [False],\n",
       "       [False]])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((len(X),1),dtype=bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.91   , 0.90835, 0.9106 ])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "never_5_clf = Never5Classifier()\n",
    "cross_val_score(never_5_clf,X_train,y_train_5, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 评估分类器性能的更好方法是混淆矩阵\n",
    "#### A类别实例被分为B类别次数\n",
    "#### 想要知道分类器将数字3和数字5混淆多少次，通过混淆矩阵的5行3列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import cross_val_predict\n",
    "\n",
    "\n",
    "y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 与 cross_val_score 相比\n",
    "* 同样执行交叉验证\n",
    "* 返回的不是评估分数，是每个折叠的预测\n",
    "* 每一个实例在模型预测时使用的数据，在训练期间从未见过"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### ross_val_predict 与cross_val_score 很相像，不过不同于返回的是评测效果，cross_val_predict 返回的是estimator 的分类结果（或回归值），这个对于后期模型的改善很重要，可以通过该预测输出对比实际目标值，准确定位到预测出错的地方，为我们参数优化及问题排查十分的重要。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[52823,  1756],\n",
       "       [  868,  4553]], dtype=int64)"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "\n",
    "\n",
    "confusion_matrix(y_train_5, y_train_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[54579,     0],\n",
       "       [    0,  5421]], dtype=int64)"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_perfect_predictions = y_train_5\n",
    "confusion_matrix(y_train_5, y_train_perfect_predictions)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 真负类: 把真正错误的数字判断正确了\n",
    "## 假负类： 把正确的数字判断成错误了\n",
    "## 真正类： 把正确的数字判断成对了\n",
    "## 假正类： 把错误的数字判断成对了"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.评估指标\n",
    "### 精度和召回率\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "\n",
    "## 正类预测的准确率 被称为分类器的精度\n",
    "\n",
    "\n",
    "$\n",
    "\\text{精度} = \\cfrac{TP}{TP + FP}\n",
    "$\n",
    "\n",
    "TP是真正类的数量，FP是假正类的数量\n",
    "\n",
    "\n",
    "\n",
    "$\n",
    "\\text{召回率TPR} = \\cfrac{TP}{TP + FN}\n",
    "$\n",
    "\n",
    " ### tp--将正类预测为正类（true positive）\n",
    "\n",
    "### fn--将正类预测为负类（false negative）\n",
    "\n",
    "### fp--将负类预测为正类（false positive）\n",
    "\n",
    "### tn--将负类预测为负类（true negative）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7216674591852908"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import precision_score, recall_score\n",
    "\n",
    "precision_score(y_train_5, y_train_pred) # 4327 / 4327 + 1276"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " ### 精度为0.7216674591852908"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.839881940601365"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recall_score(y_train_5, y_train_pred)    #  4327 / 4327 + 1094"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 召回率为0.839881940601365"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7763000852514919"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import f1_score\n",
    "f1_score(y_train_5, y_train_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### F1值是精度和召回率的调和平均值\n",
    "####  F1分数对那些具有相近精度和召回率 分类器更有利，这不一定符合你的期望"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([11764.70137129])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 返回决策值decision_function\n",
    "y_scores = sgd_clf.decision_function([some_digit])\n",
    "y_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "threshold = 0\n",
    "y_some_digit_pred = (y_scores > threshold)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_some_digit_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 提高阀值可以降低召回率，提高阀值到200000，就错了这个图\n",
    "threshold = 200000\n",
    "y_some_digit_pred = (y_scores > threshold)\n",
    "y_some_digit_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "# 返回决策值，而不是预测结果\n",
    "y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,\n",
    "                             method=\"decision_function\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 计算所有可能的阀值的精度和召回率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000,)"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_scores.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_recall_curve\n",
    "\n",
    "precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用matplotlib 绘制精度和召回相对于阀值的函数图\n",
    "def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):\n",
    "    plt.plot(thresholds, precisions[:-1], \"b--\", label=\"Precision\", linewidth=2)\n",
    "    plt.plot(thresholds, recalls[:-1], \"g-\", label=\"Recall\", linewidth=2)\n",
    "    plt.xlabel(\"Threshold\", fontsize=16)\n",
    "    plt.legend(loc=\"upper left\", fontsize=16)\n",
    "    plt.ylim([0, 1])\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plot_precision_recall_vs_threshold(precisions, recalls, thresholds)\n",
    "plt.xlim([-700000, 700000])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAf0AAAF5CAYAAACV7fNGAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3deZgU1b3G8fc3M2zOKA4yoKxmCKgoAnGCcBUZjARDEre4ReOCUeIWYx6TXPW6JGii1xizGY0oKG6XJYnmMSaKUUGNuAwuBIygLIooiiD7Osy5f5weq2eYpWemq6qX7+d5+qnT3aerfrTz+FadrjplzjkBAIDcVxB3AQAAIBqEPgAAeYLQBwAgTxD6AADkCUIfAIA8QegDAJAnCH0AAPJE5KFvZt3N7Plm+kw2s7lmdk1UdQEAkOsiDX0zK5U0VVJxE31OklTonBshqdzM+kdVHwAAuSzqI/1dkk6TtKGJPpWSZiTasyQdGXJNAADkhaIoN+ac2yBJZtZUt2JJKxPttZK+VL+DmU2QNEGSiopKD6uuLpckDRkiFRamsWAAADLQvHnzPnXOlbX0c5GGfoo2SeqUaJeogdEI59wkSZMkqaKiwi1eXKWNG6U5c6S99oquUAAA4mBm77Xmc5kY+vPkh/RfkjRY0qIoNrptm/T669KbbwaPwYOlO++MYusAAIQv1tA3s4GSznDOJZ+l/6ik582sh6SvSRre1u04Jz37rHT77dI//ylNmyaNGyctXCg98oj0zDPSiy9K27fX/dzcudI3viEdcog0f36wM9Cpk3TDDdKSJdLbb/vHqlXSVVdJQ4cGn6+p8TsTe+xR97XVq6UPP5RWrvTL2vYHH0hf/KL0+99Lu3ZJBQVS8i8hu3ZJa9ZIn3wi9evn6wAAIFWWibfWTZzlP0bSc865VU31TR7eX79+9+H9hQulyy7zwV6rpEQqL/dBnmzQIB/agwdLV1zRutpPPdUH++LF/rFtm9S9u3ToodLSpdL770s7dza/HjO/s3LMMdKnn/qditWrffDXKi6WNm+WHn/cn89QUCB17Cjtvbf/7Nq1UufOUlGRf759u3+/MTt2+J2KHTukvn1b9+8HAITPzOY55ypa/LlMDP2WSA79e+6Rbr5ZmjHDh/fUqdKFF/rgLS2VNm6UqquDz5aWSt/6lnTssdKoUVLXrsF706dLp5/u2127+h2BwYOlyZP9zsXee0sHHywdeKC0aZPvn6p99pF69JB69vTL2vZFFzX/2T339P+O5hQVBf/W/fYLwrx7d+mcc/wOxKef+mVte/363ddz7bXSO+/4kZGhQ6XPPvPrqqnxO05r1kh9+vidlOpq6Qtf8H3WrvWP0lL/PQEA0ofQTwrCq66SevWSLrnEPz/vPOmXv5Rmz/YhP3y49OMfS1//utShQ8PrdU564w0f7vvvX3eYfcOG3UcUqqqkSZN8gPfvLw0Y4HcWpk8PRhbKy/0RdGPD8tXV0ltvSV26+OB89VUf0t27S/vuK3XrJrVvL61b538OuOACH7qLF7f226ursLDuSEI6jRsnvfyydMIJ/t+2ZIn/2aNjR/+99Orl/31nnOG/cwBA4wj9pNA/9ljpiSd8+3e/k77//eC9jRv90XIu2bXLH3lLfqehtNQH6PbtfoegWzc/uvCb3/jA7dpVKivzj9p2164+bAsKfJ9f/cov331XmjXL7/T07+/7vfii/0y3bv7nk86dg1GCoiK/09Kliz/XoTVGjPA7BFVV/nyKDz6QvvpVaflyqaLCjyDUjiY8/bTfofjSl/yOw7p1/r3k5aJFfserY0df3557+lGb9eulf/3Ln5+x995+ZzD5/AsAyFSEfgND3tdfL/30p5GXlLeqq/1oQe2oyK5d0l13+XMP3nvP71B06+ZHOt54w4fw4sX+hMnt2/1PDJmgb1+/o3HKKdIRR/gRlU2b/I5DYyNDABClvA79efOqdnv98MP9URyT9WSP1aulxx7zR9sFBf6kx08+8TsN8+b5KxtqRxG6dPE/s0yb5ncchg/3R+ulpXWXHTtKy5b5kY5Fi/z5CQMG+NGJu+7y7/Xt63dKUtWvn3TccX6k4ZNP/OdPO82fu9Chg6+XvzsAYSL065kzRzrqqBgKQlbautWPOKxa5X/OWLnSX94pBVdStEZxsTRlij/XY/Nmv6OwYYM/SXSvvaQtW/wOQmGh1K5d+v49AHIboV9Plv+zkCGc849du/xVIStXSh9/7Ecaqqr8CYn//nf6tnfyyX7UYOdOf87B+ef78xAAIBmhL38t/Pz50t13+/9ZAlGrnR9h6VLpmmv8/BDV1dJhh/mfHGpHD1rrqqv8iMH48X5uBgD5idCXP5N7yBB/FAZkKuf8jsCuXf6cg507/c9Rl13mX+/bt2U7ByUl0v/+rx8RWLbMz8uw//5+NkmzupebAsgNhL78iWDJE+wA2aymxl9yuH69dNttfhTr/ff9pYstNWGCdPnl/gTGHj3SXiqAiOV16P/hD1XavFk6+ui4qwHCt327/9ngX//yk04VFkpjx/obRq1atfs9JBoydKjfqRg+3N/7oX17aeJEaeDA8OsH0HZ5HfpVVbufyAfkM+f8bI0XXyzNnNmyz5aWSt/8pvTDH3LeAJCpCH0AzVqwwN+gqaTET4u8ebP0l780/ZnOnf3IQOfO/jLDyko/l8Lhh0u9e3N1ARAHQh9Am8yeLf3kJ/7KgzVrUv/cqaf68wUkPwfBtm1+IqV99/U7CsmzNAJID0IfQNo45++r8NZb/kTCpUv97IdFRf6qg2XLWr7OQw6Rvv1tadgwf68ErrIBWo/QBxCpDz/0JxAuXCgddJAf+n/ppZatY7/9/HwGRx3ldwoApKa1oc+vcQBapUeP5mcjdE766CPp3nt9uBcX+/MIan30UXALbMmPAqxd6+cYKCvz5w1UVnIvAyBdONIHELl//EN68kl/6WEq0xiXlPidgyOPlEaNyr3bYwMtxfA+gKz1/PP+1sq1y4cf9nda3Lmz4f5du/qptk84wY8GAPmG0AeQc1at8rdOfughadKkxvuNGuV/Drj0Un9+AFcLINcR+gByXk2NdN110v33SytWNN33F7/ws3QOGSJ16BBNfUBUCH0AeWfBAn9uwL33+qsIGvP1r0t/+1t0dQFha23oF4RRDABE4ZBDpCuu8OHvnB8JuP9+f/fCZI8/7of8P/oonjqBTEHoA8gZZtJZZ0lbtwY7Acl69PB9XnjBny+webPvB+QLQh9AzjLzVwAMGFD39ZEj/cRAJSX+KoGSEunOO+OpEYgSoQ8gpxUVSYsW+fsJHHecvydAfZs3+zsSmvnHjBnR1wlEgdAHkBe6dJH++lf/u75z/rF1qzRx4u59TzvNh39Rkb9aYOnS3X8qALIRoQ8gb3XsKF17rd8BWL1a+uMf676/a5d0ww1Sv35+KuDycunCC6WNG+OpF2grQh8A5Gf5+973/A7Azp3Sb36ze59ly6S77vI3FzLz9xPYti36WoHWIvQBoJ6iIukHPwh+BvjgA38p4KBBdfv9/OdSp07BuQDjx/tzB4BMRegDQDN69vSXAs6f73/b/93vGu53331+xMBMGjGCHQBkHkIfAFrATPr+9/0IwI4d/sqAK6+Uhg+v2++ll/wOwIknxlMn0BBCHwBaqV07PwfATTdJc+f6UYDHH6/b59FHg+H/ww7zOwpAXAh9AEgTM2ncOD8KsGTJ7u+/9pq/+c+JJ0q//CWzASJ6hD4AhKC83If6rl3Sq6/Wfe/RR6Wf/MTPBvjVr3L0j+gQ+gAQooICqaLC7wC8/baf7CfZU0/5o38z6eabpVdeiadO5AdurQsAMXjySenYYxt/v6bG7wgADeHWugCQRcaO9Uf/GzdKRx/tzwVIVlDgQ3/RIn77R/oUxV0AAOSzkhLp6aeD5/WP7g880C8HDJBKS6Uf/tDfGwBoDY70ASCD1J78d/HFfra/WosXSy+/LJ1+enAJoJn0rW/FVyuyD6EPABmmoED6wx+kLVukTz7x7YMPbrjvX/7iw3/06GhrRHYi9AEgg5WV+aP+BQv8KMCKFdKDD/rL/pLNnu3Dv7LS3zIYaAihDwBZpFcv6cwzpeOPD3YCks2ZI+2xh98BuPxy5gBAXYQ+AGSxXr18+NefAEiSfvtbPwfAd7/rLwEECH0AyAG1EwA5J/31r3XfmzJFKiz0R/8vvxxPfcgMhD4A5JjjjvPh//HHu783fLjfAeB3//xE6ANAjurWzYf/p59KJ5wQvF5T43/3f+ON+GpDPAh9AMhx++wjPfKIP7rv3z94fehQaeRI6d1346sN0SL0ASBPdOzoJ/n5xz+C1154we8ImEl33x1fbYgGoQ8AeebYY/2kP5WVUrt2wesTJvipfpnrP3cR+gCQh8rKpGef9dfxL1wYvL5unTR+fHx1IVyEPgDkuYED/dF9QSIRpk71s/4h9xD6AABJ0tq1Qfuss6S77oqvFoSD0AcASJI6d5aWLAmeX3jh7rf6RXYj9AEAnysvl956q+5ryWf7I7sR+gCAOg46qO4Z/OPGSRMncvOeXEDoAwAa9MILQfv66/3Ne+bPj68etF3koW9mk81srpld08j7pWb2dzOrMjNOIwGAmBxxhPT229L++wevDR4sffvbsZWENoo09M3sJEmFzrkRksrNrH8D3c6S9JBzrkLSnmZWEWWNAIDAAQdIy5ZJixYFr02bJvXrxyQ+2SjqI/1KSTMS7VmSjmygzxpJh5jZ3pJ6S1oRTWkAgMYMGOBn8au1dKnUs6e0a1d8NaHlog79YkkrE+21kro30OcFSX0lXSbpP4l+dZjZhMTwf9Xq1avDqhUAkKSsTNq2LXj+0UdSUZHfAUB2iDr0N0nqlGiXNLL96yVd6JybKOltSbtNCOmcm+Scq3DOVZSVlYVWLACgrg4d/K15x44NXuvXz8/ZX1MTX11ITdShP0/BkP5gScsb6FMqaZCZFUo6XBK/GgFABjGTnnhCeu654LV166TCwrojAcg8UYf+o5LOMrPbJJ0qaaGZ3Vivz02SJklaL6mLpP+LtkQAQCpGjvS/6Sefzd+pk/Tee/HVhKYVRbkx59wGM6uUNEbSLc65VZLerNfnFUkHR1kXAKB1Cgqkhx+Wdu6U/vQn/9r++/tL/Q44INbS0IDIr9N3zn3mnJuRCHwAQA6YOVO6/fbg+YEHSiu49irjMCMfACAtLrlEmjUreN6nDyf3ZRpCHwCQNmPGSFOmBM8LC+OrBbsj9AEAaTV+vL9JT62iSM8eQ1MIfQBA2j3+uL9Nr+TP8P/gg3jrgUfoAwBCsWRJ0O7dO746ECD0AQCheeihoP3LX8ZXBzxCHwAQmjPOkIqLffsnP/FD/tykJz6EPgAgVPPnB+1ly/yJfTffHF89+YzQBwCEqrxc2r5dOvTQ4LWrrpIcd1aJHKEPAAhd+/bSm29K778fvFZQIK1c2fhnkH6EPgAgMr17SyNGBM979ZJ27IivnnxD6AMAIvXii9K11wbPO3SQHnggvnryCaEPAIjcxIlSRUXw/Oyz46slnxD6AIBYvPpq3TP7P/kkvlryBaEPAIjNoEFBu3t36aWX4qslHxD6AIBYTZ4ctJNP8kP6EfoAgFidd550993B8+ST/JBehD4AIHbnnx+0b7xRuvrq+GrJZYQ+ACAjJN+V76abmKM/DIQ+ACAjlJfXPYP/8svjqyVXEfoAgIxRVibtv79v3367dNJJsZaTcwh9AEBGee21oP3II5KZ9MIL8dWTSwh9AEBGKS2VNm+WOncOXhs5Uvrxj+OrKVcQ+gCAjLPHHtK6ddKDDwav3Xqr9D//E19NuYDQBwBkrDPPlD76KHj+i1/44X7n4qspmxH6AICMtu++0ooVdV8rIL1aha8NAJDxevXyR/eHHhq8ZsZNelqK0AcAZI1XX637vHt36Z574qklGxH6AICs0b69P+I/55zgtQsukN55J76asgmhDwDIOvfdJ23cGDwfMEDauTO2crIGoQ8AyEolJXWH+3//+/hqyRaEPgAga1VU+IckXXFFvLVkA0IfAJDVLr00aK9fH18d2YDQBwBktbPPDtp7783EPU0h9AEAWc1MmjIleM4lfI0j9AEAWW/8+KA9YYJUUxNfLZmM0AcA5ISXXw7ahYXSf/4TXy2ZitAHAOSEYcOkm24Kno8dG18tmYrQBwDkjCuvlO6917dXrNj9Rj35jtAHAOSU5LP5+/Th9/1khD4AIKcUFNSdna+wUNqyJb56MgmhDwDIOZdeKhUXB8+T2/mM0AcA5KSVK6X+/YPnr70WXy2ZgtAHAOSkzp2lxYuD58OHx1dLpiD0AQA5beJEv9y5k9vvEvoAgJx29dVBe9So+OrIBIQ+ACCnFRZKJ5zg23PnSlu3xltPnAh9AEDOmzYtaCfP059vCH0AQM7r0EE64gjfnj49f2+/S+gDAPLCHXcE7bvuiq+OOBH6AIC8cOihQfuii+KrI06EPgAgb8yYEbST5+jPF4Q+ACBvnHKKNGCAbz/wQLy1xIHQBwDklWeeCdqTJsVXRxwIfQBAXunZU+rVy7e/9714a4kaoQ8AyDtTpwbtp5+Or46oRR76ZjbZzOaa2TXN9LvDzL4ZVV0AgPwxenTQPuaY+OqIWqShb2YnSSp0zo2QVG5m/RvpN1LSvs65x6KsDwCQH8ykP/wheL59e3y1RCnqI/1KSbUXTMySdGT9DmbWTtLdkpab2fHRlQYAyCfJ1+p37BhfHVGKOvSLJa1MtNdK6t5An7MlvSXpFknDzOz79TuY2QQzqzKzqtWrV4dWLAAgd5lJ3boFz9euja+WqEQd+pskdUq0SxrZ/lBJk5xzqyQ9KGl0/Q7OuUnOuQrnXEVZWVloxQIActuKFUE7eca+XBV16M9TMKQ/WNLyBvq8K6k80a6Q9F74ZQEA8lH79tIZZ/j2ypVN980FUYf+o5LOMrPbJJ0qaaGZ3Vivz2RJo83sOUkXS7o14hoBAHnklluC9h//GF8dUTAX8f0FzaxU0hhJzyWG8NukoqLCVVVVtb0wAEDeMvPL9u2z40x+M5vnnKto6eciv07fOfeZc25GOgIfAIB0mDnTL3fskKqr460lTMzIBwDIeyefHLTnz4+vjrAR+gAAKLhW/9JL460jTIQ+AAAKpuOdO1faujXeWsJC6AMAIOmee4L2HnvEV0eYCH0AACR17y6ddFLwPOKL2yJB6AMAkPCnPwXtX/86vjrCQugDAJBgFgztX3FFvLWEgdAHACDJX/8atCdPjq+OMBD6AAAkqT2LX5LOPz++OsJA6AMAUM9TTwXtjRvjqyPdCH0AAOpJPtp/5pn46kg3Qh8AgAZ06+aXF18cbx3pROgDANCAM8/0yw8/zJ1r9tMe+mbWKd3rBAAgaj/9adDOlWv2mw19M2tvZiMT7UIz+2YzH7nBzCampToAAGKy115SSYlvz5oVby3pksqRfhdJ/0y0iyRNa6b/fpL2bktRAABkguuv98snn5RWrIi3lnRIJfS3Jx5yzm2XVJ38ppk9ZGadk17aT1IO340YAJAvxo8P2kcdFV8d6ZJK6NdI2mVmd5vZRkklZvaZmW00szGSvi1pgZl9OdF/sKS5IdULAEBk9tlHOu88316+PNZS0qIlJ/L9VtLxkjZLOkHSG4nPr5d0raQnzOzHkrY65xamu1AAAOLw298G7Wy/Zr8ohT6jJDnn3AJJMrNq59wcM/s08b5zzt2XeP6opNtCqhUAgMiVlPgb8TgnfeUr2X35XpNH+mb2F/kgT8XhiWWHNlUEAECGue66uCtIj+aG92+XVClJZjbCzMZLam9mZ0vqnehTZGb3SDpF0lcknWxmFlK9AABErvYsfkm6+eb46mirJkPfOfeMpDclmXz4Xy5/JH+FpD0kbZNUknh/mHNujqSVknLgHEcAADwz6cADffuqq+KtpS1SPZHPOedukjRU0hbn3GDn3ED5s/S3OOe+65zbkOg7W9KI9JcKAEB8pk8P2tu3x1dHW7R0Gt6OkpKn2TVJ0+v1WSDpsLYUBQBApjn00KB96aXx1dEW5po5DTEx8c6Hkv478VKNpB2Stkj6KPHeSufcpkT/IyT1dM7NCKvoZBUVFa6qqiqKTQEA8tzAgdJ//uPbcZ7Fb2bznHMVLf1cKpfs7ZL0tqQzJdX+E4skFSce+0pqZ2aLJc2SNCWqwAcAIEozZ0qHHOLbc+ZIo0bFW09LNRv6iSP4JofrzayPpKMlnS7pNTM7yjn3r/SUCABAZjj44KBdWZl91+y3+Na6ZlZmZl2TX3POve+cu885d6ykwQQ+ACBXJV+z/+KL8dXRGqncWreTmV1hXkdJF0g6u7H+tTP3AQCQi372s6CdbSf0pXqk/0NJh0i6Q/7a/B1mNs/MPjCzpfUei8zsp2EVDABA3H7wA798/fV462ipZkPfObdV0k75sN8mf2vdnZJK5U/u6yRpfNJygaQfmVlhSDUDABCrq68O2itXxldHSzU39/7XzGy0/Cx8FZK6S/pi7fuJGfi2JpbbEstfSTpO/tI+AAByTllZ0L4ti24z19yR/gOS7pdUJukWScdIOqOpDzjnXnTOPeOamwAAAIAsZSadcIJv33dfrKW0SHNz73d1zvWW9IH83Pv3S7qhse7pLQ0AgMxVe43+2rVSdXW8taQqlbP3C+Wv5y+Q1F5+6t0C/5ZdJ6k0eVn7CLNoAADi9r3vBe0lS+KroyVSOXu/Y+KxWdIriXZ7+Tn3u8v/BFAqPwrQNfFanzCKBQAgU3TqJPVJpN0zz8RbS6pSmZFvs5ldLGmHc26ymZ0iaalzbp6ZfVdSP+fc1c2sBgCAnNO/v/T++9K//x13JalJ9Tr9b0t618xOlzRN0ltmdp+kKyU9HVJtAABktC9/2S9ffjneOlLV5JG+mZ0mf23+VPnr7w9KvDVW0jr5k/qKzey4pI8Vyl/iN9M5tyvtFQMAkCEOP9wvX3st3jpS1dzw/k8lbZc/M9/Jn8Rnkv6ceH+JpE2J15LX2UHS3xLvAQCQk8aMCdqffSaVlsZXSyqau2TvIOfcEElHSZor6b/lw/9kSX+XtLek/5NU4ZwbmngMcs4NSNydDwCAnFVcHLTvvju+OlKV6m/6M+TPyn9L/qj+SefcNyWNk3SapH+ZmTXxeQAAclK/fn6ZDb/rN3v2fsK5zrmPJcnMvuCc2yJJzrkqMxsuaRgz8AEA8tERR/jr9Ldvj7uS5qV0pF8b+In2e/Xeq3bOZdkdhQEASI/Ro/1yzpx460hFqsP7AACgAQcc4JebNkm7MvyaNUIfAIA2qKgI2scfH18dqSD0AQBog3btgvbjj8dXRyoIfQAA2mjRoqD96qvx1dEcQh8AgDYaMCBoX5fB95kl9AEASIPLLvPLJ56It46mEPoAAKTBuecG7UyduYbQBwAgDYYMCdqZ+rs+oQ8AQBqYSQcl7kU7aVK8tTSG0AcAIE2GDfPLqVPjraMxhD4AAGkyYYJfVlfHW0djIg99M5tsZnPN7Jpm+nU3s9ejqgsAgLZK/l3/ww/jq6MxkYa+mZ0kqdA5N0JSuZn1b6L7rZI6RVMZAABtt8ceQfv1DDxsjfpIv1LSjER7lqQjG+pkZkdL2ixpVTRlAQCQHoce6pfPPhtvHQ2JOvSLJa1MtNdK6l6/g5m1l3StpCsbW4mZTTCzKjOrWr16dSiFAgDQGnvt5ZcdO8ZbR0OiDv1NCobsSxrZ/pWS7nDOrWtsJc65Sc65CudcRVlZWQhlAgDQOmPG+OUrr8RbR0OiDv15Cob0B0ta3kCfYyRdYmazJQ0xs3uiKQ0AgLbr2tUvn3oq3joaUhTx9h6V9LyZ9ZD0NUmnm9mNzrnPz+R3zh1V2zaz2c658yOuEQCAVvva14L2tm2ZNcwf6ZG+c26D/Ml8L0ka7Zx7MznwG+hfGVFpAACkxRe+ELQffzy+OhoS+XX6zrnPnHMznHOcmQ8AyEnl5X558snx1lEfM/IBAJBm3/lO0N65M7466iP0AQBIs2uSfri++eb46qiP0AcAIM3atZP69vXt666Lt5ZkhD4AACG49dagXVMTXx3JCH0AAELwrW8F7Zkz46sjGaEPAEAIzKT+idvKLV8eaymfI/QBAAjJuHF+ecst8dZRi9AHACAkPXv6ZaZctkfoAwAQknPP9cuNGyXnYi1FEqEPAEBo9tknaK9dG18dtQh9AABCUlAg7b+/b0+bFmspkgh9AABCtXq1X378cbx1SIQ+AAChOuccv7zhhnjrkAh9AABCNWZM3BUECH0AAEL09a8H7fXr46tDIvQBAAhVu3ZSly6+nTwffxwIfQAAQlZS4pfFxfHWQegDABCy8eP9csqUeOsg9AEACFmPHn75zjvx1kHoAwAQsgsuCNrvvx9fHYQ+AAAhMwvaDz8cXx2EPgAAERg61C/nzImvBkIfAIAI1M7M98QT8dVA6AMAEIHjjw/a1dXx1EDoAwAQgdq77UnS8uXx1EDoAwAQsRUr4tkuoQ8AQET69PHLpUvj2T6hDwBARA47zC/feiue7RP6AABEpEMHv1yzJp7tE/oAAERk7Fi/nDo1nu0T+gAARKR2eF+K53p9Qh8AgIgMGhS0f/Sj6LdP6AMAEKFLLvHLhQuj3zahDwBAhJLvuBc1Qh8AgAglz8znXLTbJvQBAIhQ585Be8OGaLdN6AMAEJOop+Ml9AEAiFjtpXvvvBPtdgl9AAAi9umnfjl7drTbJfQBAIjY8OF++cYb0W6X0AcAIGK1of/cc9Ful9AHACBiJ54YtKO8bI/QBwAgYr17B+2PP45uu4Q+AAARKyiQunb17enTI9xudJsCAAC1amr8sn376LZJ6AMAEINzz/XLa6+NbpuEPgAAMai9XG/Nmui2SegDABCDX/86aEd1Bj+hDwBADAYNCtq33RbNNgl9AABiYBYE/49+FM3RPqEPAEBMHnkkaC9ZEv72CH0AAGLSr59UUuLbUdx8h9AHACBGX/yiX06dGv62CH0AAGI0dqxfrlwZ/rYIfQAAYnT66X65bJm0dWu42yL0AQCIUfKlewsWhLstQh8AgBgVFkpFRb5dO0tfWCIPfTObbGZzzeyaRt7vbGb/MLNZZvaImUV4KzEdB/EAAAloSURBVAIAAKJ30kl+OWFCuNuJNPTN7CRJhc65EZLKzax/A93OlHSbc+6rklZJOjbKGgEAiNpZZwXt6urwthP1kX6lpBmJ9ixJR9bv4Jy7wzn3VOJpmaRPoikNAIB4fOMbQfvll8PbTtShXyyp9qKEtZK6N9bRzEZIKnXOvdTAexPMrMrMqlavXh1OpQAARGjgQL+cMye8bUQd+pskdUq0Sxrbvpl1kfR7Sec19L5zbpJzrsI5V1FWVhZKoQAAROmww/zyN78JbxtRh/48BUP6gyUtr98hceLeTElXOefei640AADiM3y4X4Y5gB116D8q6Swzu03SqZIWmtmN9fp8V9KXJP2Pmc02s9MirhEAgMiNHx+0N28OZxtF4ay2Yc65DWZWKWmMpFucc6skvVmvz52S7oyyLgAA4tapU9BesEA6/PD0byPy6/Sdc58552YkAh8AACTU3nznn/8MZ/3MyAcAQIbo2dMvp00LZ/2EPgAAGWLUKL8Ma4IeQh8AgAwxcqRfvv12OOsn9AEAyBDDhgXtzz5L//oJfQAAMsReewXtd95J//oJfQAAMki/fn75yivpXzehDwBABikv98vp09O/bkIfAIAMUhv6W7akf92EPgAAGeTUU/3ytdfSv25CHwCADFJ7rb4krV2b3nUT+gAAZJDCQmnPPX373XfTu25CHwCADLNjh18S+gAA5Lgjj/TLGTPSu15CHwCADHPUUX65bVt610voAwCQYYYM8cs5c9K7XkIfAIAM06ePX27bJtXUpG+9hD4AABlm4MCg/ec/p2+9hD4AABmmfXupa1ffrp2sJx0IfQAAMtAjjwTtdN1ml9AHACAD/dd/Be1evdKzTkIfAIAMVFAgXX65b6fr5juEPgAAGeqWW4L2unVtXx+hDwBAhmrXLmhfdlnb10foAwCQwcaN88sHHpCqq9u2LkIfAIAM9vDDQfuxx9q2LkIfAIAM1rmzdNhhvt3WIX5CHwCADHfMMX75wQdtWw+hDwBAhrvooqD9ne+0fj2EPgAAGa5v36D90EOtXw+hDwBAFtiyRerWrW3rIPQBAMgCnTpJH38sLVnS+nUQ+gAAZJHy8tZ/ltAHACBPEPoAAOQJQh8AgDxB6AMAkCcIfQAA8gShDwBAniD0AQDIE4Q+AAB5gtAHACBPEPoAAOQJQh8AgDxB6AMAkCcIfQAA8gShDwBAniD0AQDIE4Q+AAB5gtAHACBPEPoAAOQJQh8AgDxB6AMAkCcIfQAA8gShDwBAniD0AQDIE4Q+AAB5IvLQN7PJZjbXzK5pSx8AANAykYa+mZ0kqdA5N0JSuZn1b00fAADQclEf6VdKmpFoz5J0ZCv7AACAFiqKeHvFklYm2mslfak1fcxsgqQJiafbzWxBmuvE7rpK+jTuInIc33H4+I7Dx3ccjQNa86GoQ3+TpE6JdokaHmloto9zbpKkSZJkZlXOuYr0l4pkfM/h4zsOH99x+PiOo2FmVa35XNTD+/MUDNcPlrS8lX0AAEALRX2k/6ik582sh6SvSTrdzG50zl3TRJ/hEdcIAEBOivRI3zm3Qf5EvZckjXbOvVkv8Bvqs76Z1U4KoVTsju85fHzH4eM7Dh/fcTRa9T2bcy7dhQAAgAzEjHwAAOSJrAl9ZvILX3Pfn5l1NrN/mNksM3vEzNpHXWMuSPXv1My6m9nrUdWVS1rwHd9hZt+Mqq5cksL/L0rN7O9mVmVmd0VdX65I/H/g+Wb6pJx9WRH6zOQXvhS/vzMl3eac+6qkVZKOjbLGXNDCv9NbFVy+ihSl+h2b2UhJ+zrnHou0wByQ4nd8lqSHEpfv7WlmXMbXQmZWKmmq/Pw1jfVpUfZlReiLmfyiUKlmvj/n3B3OuacST8skfRJNaTmlUin8nZrZ0ZI2y+9coWUq1cx3bGbtJN0tabmZHR9daTmjUs3/Ha+RdIiZ7S2pt6QV0ZSWU3ZJOk3Shib6VKoF2ZctoV9/lr7ureyDxqX8/ZnZCEmlzrmXoigsxzT7PSd+NrlW0pUR1pVLUvlbPlvSW5JukTTMzL4fUW25IpXv+AVJfSVdJuk/iX5oAefchhSuYGtR9mVL6KdlJj80KaXvz8y6SPq9pPMiqivXpPI9XynpDufcusiqyi2pfMdDJU1yzq2S9KCk0RHVlitS+Y6vl3Shc26ipLcljY+otnzTouzLlmBkJr/wNfv9JY5AZ0q6yjn3XnSl5ZRU/k6PkXSJmc2WNMTM7ommtJyRynf8rqTyRLtCEn/PLZPKd1wqaZCZFUo6XBLXh4ejRdmXFdfpm9lekp6X9LQSM/lJOiV5Yp8G+gxPYVgECSl+xxdJ+oWkNxMv3emcmx51rdksle+5Xv/ZzrnK6CrMfin+Le8paYr8UGg7SSc751Y2sDo0IMXveJike+WH+OdKOtE5tymGcrNe7f8HzGygpDPakn1ZEfrS52cxjpH0XGJIrlV90Di+v2jwPYeP7zh8fMeZoyX/LbIm9AEAQNtky2/6AACgjQh9AADyBKEPQGZWnDjLGkAOI/QBSP5a32ozcyk8ptR+yMyOSvEzyY/eMf47gbxWFHcBADJCH0nbJe1IPH9X0m2S7qjXb7akj5Ke70wsS1PcxptJnwEQMUIfgJxzn8+LbmZflrSPpMfqzwpoZvtJej/pperE55udPTAxB/vnnwEQPYb3AdR3naQXnHP/Tn7RzDrK32hpSdLLO+v1+bSB4fxX662f0AdiQugDkPT5yXz3Szpa0sVJr3dJ3PXvZ/JTqc5vYjVbJI12zplzziT9UNLWEMsG0AIM7wN5zsx6STpVPqBrJI2td5S/S9KT8if7/dw519QtlWtSfA1ADAh9II+ZWQf5e3AXyN9m9h7nXJ0jc+fcejPb1zm3JpVVpvgagBgwvA/kMefcdvkbdBwo6XhJWxq6zE5S8m/1ZzSxyo6Snk363K8TrwHIABzpA3nOObch0dwi6c+SftRE9/mStjXx/gDtfmTPiXtAhiD0AdSqkbTJObe8sQ5mVqMmfqPndtZAZmN4H0BbtObAgel+gZhwpA8g2Tlmdk4zfZL/v9FOkhK/36eqXYurApAWHOkDqOUkPSg/pW5jjw2qe2JekaT1tdflN/WQ9IWkzwCIgTnXkh10AAiYWZGk4lR+yzezAkl7ye8k8D8eIAaEPgAAeYLhfQAA8gShDwBAniD0AQDIE4Q+AAB5gtAHACBPEPoAAOSJ/wer2ebmed29VAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "def plot_precision_vs_recall(precisions, recalls):\n",
    "    plt.plot(recalls, precisions, \"b-\", linewidth=2)\n",
    "    plt.xlabel(\"召回\", fontsize=16)\n",
    "    plt.ylabel(\"精度\", fontsize=16)\n",
    "    plt.axis([0, 1, 0, 1])\n",
    "\n",
    "plt.figure(figsize=(8, 6))\n",
    "plot_precision_vs_recall(precisions, recalls)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 通过选择阀值来实现最佳的精度/召回率权衡\n",
    "\n",
    "### 目标设定为90%的精度，阀值大概在30000左右 , 设置了阀值为30000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_train_pred_90 = (y_scores > 30000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7752968279284069"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "precision_score(y_train_5, y_train_pred_90)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8070466703560228"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recall_score(y_train_5, y_train_pred_90)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ROC 曲线\n",
    "### 本质是 真正类率tpr和假正类率fpr（错误的分为正类的负类实例比例）\n",
    "### 与召回/精度曲线非常相似"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import roc_curve\n",
    "\n",
    "fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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vF6v07FERMRl3DHSD1N+v58HH3yQwYMHY62lbdu23HbbbSp8ERGpFa4o/XCc3d+xYweXXHIJt956K36/n6KiyFpKWEREQs8VpR9uFi9eTFpaGkuXLuWpp57iP//5D/HxkbOUsIiIOMMl+/TDZ6hfUFDA6NGjadSoEUuWLOGss85yOpKIiEQIV5R+ONi8eTMtWrQgISGBt99+m1NPPZWEhASnY4mISARxxfR+Xd+n/9JLL3HWWWfxwAMPANCpUycVvoiIhJw7St/pAEeRn5/P2LFjGTp0KB07duTqq692OpKIiEQwV5R+XfTll1+SkZHBrFmzuPPOO1m6dCmnnHKK07FERCSCuWKffl2c3i8sLKSgoIAlS5bQt29fp+OIiIhopF+T9uzZw6xZswDo1q0b69atU+GLiEid4YrSrwun7P3vf/+jS5cu/O53v+PHH38EICYmxtlQIiIiB3FF6TuprKyMqVOncuGFFxIfH8+nn36qffciIlInuWKfvlMDfWstv/zlL3nrrbcYOXIkjz/+OMnJyc6EERERqYQrSt+pyX1jDFdffTXDhg1j5MiRDqUQERGpGleUfigVFRUxceJE0tPTGTNmDCNGjHA6koiISJW4Yp++CdE5e2vXrqV79+489thjfP/99yF5ThERkZqikX4VWGt57rnnuOmmm0hISOCNN97gkksucTqWiIhItbhjpF/Lj5+Zmcm1115L9+7dycrKUuGLiEhYcsVIv7Zm93ft2kVqairnnHMOixYt4qKLLsLr9dbOk4mIiNQyV4z0a5rf7+dvf/sbp5xyCitWrABg4MCBKnwREQlrGukfZseOHYwaNYrFixdzxRVXcNppp9Xcg4uIiDhII/2DLF68mLS0NP73v//x1FNP8e9//5uUlBSnY4mIiNQId4z0a+hQvk8//ZTGjRvz7rvv0rFjxxp5TBERkboi4kf669ev5+OPPwZg0qRJrFixQoUvIiKu5IrSP959+vPmzaNLly6MHTsWn8+H1+slPj6+ZsOJiIjUEa4o/erKz8/nmmuu4eqrr6ZTp04sWrRIR+aLiIjruWKffnXs2rWL888/n++++45JkyZx9913ExUVcS+DiIhEIFe0XXXW3m/cuDEXXnghTz75JBdeeGEtphIREalbImJ6f8+ePQwfPpz169djjFHhi4hIRHJF6R9rnL906VLS0tL497//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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "def plot_roc_curve(fpr, tpr, label=None):\n",
    "    plt.plot(fpr, tpr, linewidth=2, label=label)\n",
    "    plt.plot([0, 1], [0, 1], 'k--')\n",
    "    plt.axis([0, 1, 0, 1])\n",
    "    plt.xlabel('假正类率', fontsize=16)\n",
    "    plt.ylabel('真正类率', fontsize=16)\n",
    "\n",
    "plt.figure(figsize=(8, 6))\n",
    "plot_roc_curve(fpr, tpr)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9667169899882537"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算曲线下面积AUC，虚线是随机分类0.5到1\n",
    "from sklearn.metrics import roc_auc_score\n",
    "\n",
    "roc_auc_score(y_train_5, y_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\ensemble\\weight_boosting.py:29: DeprecationWarning: numpy.core.umath_tests is an internal NumPy module and should not be imported. It will be removed in a future NumPy release.\n",
      "  from numpy.core.umath_tests import inner1d\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier\n",
    "forest_clf = RandomForestClassifier(n_estimators=10, random_state=42)\n",
    "y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,\n",
    "                                    method=\"predict_proba\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1. , 0. ],\n",
       "       [1. , 0. ],\n",
       "       [1. , 0. ],\n",
       "       ...,\n",
       "       [0.6, 0.4],\n",
       "       [0.9, 0.1],\n",
       "       [1. , 0. ]])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_probas_forest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 绘制ROC曲线，需要决策值不是概率，直接使用正类的概率作为决策值：\n",
    "y_scores_forest = y_probas_forest[:, 1] \n",
    "fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0. , 0. , 0. , ..., 0.4, 0.1, 0. ])"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_scores_forest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8, 6))\n",
    "plt.plot(fpr, tpr, \"b:\", linewidth=2, label=\"SGD\")\n",
    "plot_roc_curve(fpr_forest, tpr_forest, \"Random Forest\")\n",
    "plt.legend(loc=\"lower right\", fontsize=16)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9926873937049405"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "roc_auc_score(y_train_5, y_scores_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9850945494994439"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_pred_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3)\n",
    "precision_score(y_train_5, y_train_pred_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8168234643054787"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recall_score(y_train_5, y_train_pred_forest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sgd_clf.fit(X_train, y_train)\n",
    "sgd_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  59926.13479493, -419617.81752884, -449712.5605328 ,\n",
       "          21210.8559416 , -395405.65079429,   11764.70137129,\n",
       "        -765812.22514852, -134190.53095006, -967522.21181707,\n",
       "        -652420.7273181 ]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 内部实际上训练了10个二元分类器，获得图片的决策分数，然后选择了分数最高的类别\n",
    "# 返回10个分数，每个类别1个\n",
    "some_digit_scores = sgd_clf.decision_function([some_digit])\n",
    "some_digit_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmax(some_digit_scores)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 目标类别列表会存储在classes_这个属性中，按值大小排列，\n",
    "sgd_clf.classes_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sgd_clf.classes_[np.argmax(some_digit_scores)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5.])"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.multiclass import OneVsOneClassifier\n",
    "ovo_clf = OneVsOneClassifier(SGDClassifier(max_iter=5, tol=-np.infty, random_state=42))\n",
    "ovo_clf.fit(X_train, y_train)\n",
    "ovo_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(ovo_clf.estimators_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5.])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用随机森林\n",
    "forest_clf.fit(X_train, y_train)\n",
    "forest_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0. , 0. , 0. , 0.1, 0. , 0.9, 0. , 0. , 0. , 0. ]])"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 随机森林直接将实例分为多个类别，调用predict_proba()可以获得分类器将每个实例分类为每个类别的概率列表\n",
    "forest_clf.predict_proba([some_digit])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.85557888, 0.86979349, 0.84562684])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用交叉验证评估SGD的准确率\n",
    "cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.90816837, 0.91494575, 0.90713607])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将输入进行简单缩放 ，可以得到准确率 90 %以上\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "scaler = StandardScaler()\n",
    "X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))\n",
    "cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring=\"accuracy\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 错误分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n",
      "c:\\users\\administrator\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\sklearn\\linear_model\\stochastic_gradient.py:128: FutureWarning: max_iter and tol parameters have been added in <class 'sklearn.linear_model.stochastic_gradient.SGDClassifier'> in 0.19. If both are left unset, they default to max_iter=5 and tol=None. If tol is not None, max_iter defaults to max_iter=1000. From 0.21, default max_iter will be 1000, and default tol will be 1e-3.\n",
      "  \"and default tol will be 1e-3.\" % type(self), FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[5743,    2,   22,    9,    9,   43,   42,    8,   39,    6],\n",
       "       [   2, 6463,   44,   26,    6,   44,    6,   13,  127,   11],\n",
       "       [  62,   35, 5339,   95,   79,   23,   86,   53,  169,   17],\n",
       "       [  56,   36,  134, 5330,    4,  248,   31,   56,  144,   92],\n",
       "       [  18,   26,   40,    8, 5362,    8,   58,   37,   76,  209],\n",
       "       [  68,   40,   37,  176,   74, 4622,  103,   33,  179,   89],\n",
       "       [  33,   23,   51,    2,   38,   93, 5630,    6,   42,    0],\n",
       "       [  28,   23,   64,   36,   51,   11,    6, 5812,   15,  219],\n",
       "       [  51,  160,   62,  142,   14,  161,   56,   28, 5036,  141],\n",
       "       [  43,   34,   22,   86,  166,   25,    3,  213,   89, 5268]],\n",
       "      dtype=int64)"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3)\n",
    "conf_mx = confusion_matrix(y_train, y_train_pred)\n",
    "conf_mx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 使用matplotlib的matshow 函数来查看混淆矩阵的图像表示\n",
    "plt.matshow(conf_mx, cmap = plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [],
   "source": [
    " # 数字5 看起来比较暗，说明1. 数字5图片较少  2. 分类器在数字5上执行效果不如其他数字上好\n",
    "# 假设把焦点放在错误上，为取得错误率，而不是错误绝对值，需要将混淆矩阵中每个值除以相应类别中的图片数量\n",
    "\n",
    "row_sums = conf_mx.sum(axis=1, keepdims=True)\n",
    "norm_conf_mx = conf_mx / row_sums"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 用0填充对角线 只保留错误，重新绘制\n",
    "np.fill_diagonal(norm_conf_mx, 0)\n",
    "plt.matshow(norm_conf_mx, cmap=plt.cm.gray)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_digits(instances, images_per_row=10, **options):\n",
    "    size = 28\n",
    "    images_per_row = min(len(instances), images_per_row)\n",
    "    images = [instance.reshape(size,size) for instance in instances]\n",
    "    n_rows = (len(instances) - 1) // images_per_row + 1\n",
    "    row_images = []\n",
    "    n_empty = n_rows * images_per_row - len(instances)\n",
    "    images.append(np.zeros((size, size * n_empty)))\n",
    "    for row in range(n_rows):\n",
    "        rimages = images[row * images_per_row : (row + 1) * images_per_row]\n",
    "        row_images.append(np.concatenate(rimages, axis=1))\n",
    "    image = np.concatenate(row_images, axis=0)\n",
    "    plt.imshow(image, cmap = matplotlib.cm.binary, **options)\n",
    "    plt.axis(\"off\")\n",
    "\n",
    "\n",
    "# 查看数字3和数字5的例子\n",
    "cl_a, cl_b = 3, 5\n",
    "X_aa = X_train[(y_train == cl_a) & (y_train_pred == cl_a)]\n",
    "X_ab = X_train[(y_train == cl_a) & (y_train_pred == cl_b)]\n",
    "X_ba = X_train[(y_train == cl_b) & (y_train_pred == cl_a)]\n",
    "X_bb = X_train[(y_train == cl_b) & (y_train_pred == cl_b)]\n",
    "\n",
    "plt.figure(figsize=(8,8))\n",
    "plt.subplot(221); \n",
    "plot_digits(X_aa[:25], images_per_row=5)\n",
    "plt.subplot(222); \n",
    "plot_digits(X_ab[:25], images_per_row=5)\n",
    "plt.subplot(223);\n",
    "plot_digits(X_ba[:25], images_per_row=5)\n",
    "plt.subplot(224); \n",
    "plot_digits(X_bb[:25], images_per_row=5)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 多标签分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "\n",
    "y_train_large = (y_train >= 7)\n",
    "y_train_odd = (y_train % 2 == 1)\n",
    "y_multilabel = np.c_[y_train_large, y_train_odd]\n",
    "\n",
    "knn_clf = KNeighborsClassifier()\n",
    "knn_clf.fit(X_train, y_multilabel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False,  True]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# knn支持多标签分类，不是所有的分类器都支持\n",
    "knn_clf.predict([some_digit])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 多输出分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 增加噪声，目标将图片还原为原始图片 创建训练集和测试集\n",
    "noise = np.random.randint(0, 100, (len(X_train), 784))\n",
    "X_train_mod = X_train + noise\n",
    "noise = np.random.randint(0, 100, (len(X_test), 784))\n",
    "X_test_mod = X_test + noise\n",
    "y_train_mod = X_train\n",
    "y_test_mod = X_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "some_index = 5500\n",
    "plt.subplot(121);plt.imshow(X_test_mod[some_index].reshape(28, 28), cmap = matplotlib.cm.binary)\n",
    "plt.subplot(122);plt.imshow(y_test_mod[some_index].reshape(28, 28), cmap = matplotlib.cm.binary)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "knn_clf.fit(X_train_mod, y_train_mod)\n",
    "clean_digit = knn_clf.predict([X_test_mod[some_index]])\n",
    "\n",
    "plt.imshow(clean_digit.reshape(28, 28), cmap = matplotlib.cm.binary)\n",
    "plt.show()\n",
    "                    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 垃圾邮件分类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "SPAM_PATH = os.path.join(\"datasets\", \"spam\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "HAM_DIR = os.path.join(SPAM_PATH, \"easy_ham\")\n",
    "SPAM_DIR = os.path.join(SPAM_PATH, \"spam\")\n",
    "ham_filenames = [name for name in sorted(os.listdir(HAM_DIR)) if len(name) > 20]\n",
    "spam_filenames = [name for name in sorted(os.listdir(SPAM_DIR)) if len(name) > 20]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 我们可以使用python的“email”模块解析这些电子邮件（它处理邮件头、编码等）\n",
    "import email\n",
    "import email.policy\n",
    "\n",
    "def load_email(is_spam, filename, spam_path=SPAM_PATH):\n",
    "    directory = \"spam\" if is_spam else \"easy_ham\"\n",
    "    with open(os.path.join(spam_path, directory, filename), \"rb\") as f:\n",
    "        return email.parser.BytesParser(policy=email.policy.default).parse(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Martin A posted:\n",
      "Tassos Papadopoulos, the Greek sculptor behind the plan, judged that the\n",
      " limestone of Mount Kerdylio, 70 miles east of Salonika and not far from the\n",
      " Mount Athos monastic community, was ideal for the patriotic sculpture. \n",
      " \n",
      " As well as Alexander's granite features, 240 ft high and 170 ft wide, a\n",
      " museum, a restored amphitheatre and car park for admiring crowds are\n",
      "planned\n",
      "---------------------\n",
      "So is this mountain limestone or granite?\n",
      "If it's limestone, it'll weather pretty fast.\n",
      "\n",
      "------------------------ Yahoo! Groups Sponsor ---------------------~-->\n",
      "4 DVDs Free +s&p Join Now\n",
      "http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM\n",
      "---------------------------------------------------------------------~->\n",
      "\n",
      "To unsubscribe from this group, send an email to:\n",
      "forteana-unsubscribe@egroups.com\n",
      "\n",
      " \n",
      "\n",
      "Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/\n"
     ]
    }
   ],
   "source": [
    "ham_emails = [load_email(is_spam=False, filename=name) for name in ham_filenames]\n",
    "spam_emails = [load_email(is_spam=True, filename=name) for name in spam_filenames]\n",
    "print(ham_emails[1].get_content().strip())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 分割邮件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help wanted.  We are a 14 year old fortune 500 company, that is\n",
      "growing at a tremendous rate.  We are looking for individuals who\n",
      "want to work from home.\n",
      "\n",
      "This is an opportunity to make an excellent income.  No experience\n",
      "is required.  We will train you.\n",
      "\n",
      "So if you are looking to be employed from home with a career that has\n",
      "vast opportunities, then go:\n",
      "\n",
      "http://www.basetel.com/wealthnow\n",
      "\n",
      "We are looking for energetic and self motivated people.  If that is you\n",
      "than click on the link and fill out the form, and one of our\n",
      "employement specialist will contact you.\n",
      "\n",
      "To be removed from our link simple go to:\n",
      "\n",
      "http://www.basetel.com/remove.html\n",
      "\n",
      "\n",
      "4139vOLW7-758DoDY1425FRhM1-764SMFc8513fCsLl40\n"
     ]
    }
   ],
   "source": [
    "print(spam_emails[6].get_content().strip()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 电子邮件实际上有很多部分，带有图像和附件（它们可以有自己的附件）。查看邮件的各种类型的结构：\n",
    "def get_email_structure(email):\n",
    "    if isinstance(email, str):\n",
    "        return email\n",
    "    payload = email.get_payload()\n",
    "    if isinstance(payload, list):\n",
    "        return \"multipart({})\".format(\", \".join([\n",
    "            get_email_structure(sub_email)\n",
    "            for sub_email in payload\n",
    "        ]))\n",
    "    else:\n",
    "        return email.get_content_type()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Counter({1: 1, 4: 2, 2: 3, 3: 2})"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import Counter\n",
    "\n",
    "a = [1,4,2,3,2,3,4,2]  \n",
    " \n",
    "b = Counter(a) #求数组中每个数字出现了几次\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('text/plain', 2408),\n",
       " ('multipart(text/plain, application/pgp-signature)', 66),\n",
       " ('multipart(text/plain, text/html)', 8),\n",
       " ('multipart(text/plain, text/plain)', 4),\n",
       " ('multipart(text/plain)', 3),\n",
       " ('multipart(text/plain, application/octet-stream)', 2),\n",
       " ('multipart(text/plain, text/enriched)', 1),\n",
       " ('multipart(text/plain, application/ms-tnef, text/plain)', 1),\n",
       " ('multipart(multipart(text/plain, text/plain, text/plain), application/pgp-signature)',\n",
       "  1),\n",
       " ('multipart(text/plain, video/mng)', 1),\n",
       " ('multipart(text/plain, multipart(text/plain))', 1),\n",
       " ('multipart(text/plain, application/x-pkcs7-signature)', 1),\n",
       " ('multipart(text/plain, multipart(text/plain, text/plain), text/rfc822-headers)',\n",
       "  1),\n",
       " ('multipart(text/plain, multipart(text/plain, text/plain), multipart(multipart(text/plain, application/x-pkcs7-signature)))',\n",
       "  1),\n",
       " ('multipart(text/plain, application/x-java-applet)', 1)]"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from collections import Counter\n",
    "\n",
    "def structures_counter(emails):\n",
    "    structures = Counter()\n",
    "    for email in emails:\n",
    "        structure = get_email_structure(email)\n",
    "        structures[structure] += 1\n",
    "    return structures\n",
    "\n",
    "structures_counter(ham_emails).most_common()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('text/plain', 218),\n",
       " ('text/html', 183),\n",
       " ('multipart(text/plain, text/html)', 45),\n",
       " ('multipart(text/html)', 20),\n",
       " ('multipart(text/plain)', 19),\n",
       " ('multipart(multipart(text/html))', 5),\n",
       " ('multipart(text/plain, image/jpeg)', 3),\n",
       " ('multipart(text/html, application/octet-stream)', 2),\n",
       " ('multipart(text/plain, application/octet-stream)', 1),\n",
       " ('multipart(text/html, text/plain)', 1),\n",
       " ('multipart(multipart(text/html), application/octet-stream, image/jpeg)', 1),\n",
       " ('multipart(multipart(text/plain, text/html), image/gif)', 1),\n",
       " ('multipart/alternative', 1)]"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "structures_counter(spam_emails).most_common()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Return-Path : <12a1mailbot1@web.de>\n",
      "Delivered-To : zzzz@localhost.spamassassin.taint.org\n",
      "Received : from localhost (localhost [127.0.0.1])\tby phobos.labs.spamassassin.taint.org (Postfix) with ESMTP id 136B943C32\tfor <zzzz@localhost>; Thu, 22 Aug 2002 08:17:21 -0400 (EDT)\n",
      "Received : from mail.webnote.net [193.120.211.219]\tby localhost with POP3 (fetchmail-5.9.0)\tfor zzzz@localhost (single-drop); Thu, 22 Aug 2002 13:17:21 +0100 (IST)\n",
      "Received : from dd_it7 ([210.97.77.167])\tby webnote.net (8.9.3/8.9.3) with ESMTP id NAA04623\tfor <zzzz@spamassassin.taint.org>; Thu, 22 Aug 2002 13:09:41 +0100\n",
      "From : 12a1mailbot1@web.de\n",
      "Received : from r-smtp.korea.com - 203.122.2.197 by dd_it7  with Microsoft SMTPSVC(5.5.1775.675.6);\t Sat, 24 Aug 2002 09:42:10 +0900\n",
      "To : dcek1a1@netsgo.com\n",
      "Subject : Life Insurance - Why Pay More?\n",
      "Date : Wed, 21 Aug 2002 20:31:57 -1600\n",
      "MIME-Version : 1.0\n",
      "Message-ID : <0103c1042001882DD_IT7@dd_it7>\n",
      "Content-Type : text/html; charset=\"iso-8859-1\"\n",
      "Content-Transfer-Encoding : quoted-printable\n"
     ]
    }
   ],
   "source": [
    "# 正常邮件更多的是纯文本，而垃圾邮件有相当多的HTML。\n",
    "# 查看邮件头\n",
    "for header, value in spam_emails[0].items():\n",
    "    print(header,\":\",value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Life Insurance - Why Pay More?'"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spam_emails[0][\"Subject\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 拆分训练集和测试集合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X = np.array(ham_emails + spam_emails)\n",
    "y = np.array([0] * len(ham_emails) + [1] * len(spam_emails))\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 首先需要一个函数来将html转换为纯文本，使用[Beautifulsoup]库，下面的函数首先删除`<head>`部分，然后将所有`<a>`标记转换为单词hyperlink，然后去掉所有html标记，只留下纯文本。为了可读性，它还用一个换行符替换多个换行符，最后它取消了HTML实体（例如`&gt；`或`&nbsp；`）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "from html import unescape\n",
    "\n",
    "def html_to_plain_text(html):\n",
    "    text = re.sub('<head.*?>.*?</head>', '', html, flags=re.M | re.S | re.I)\n",
    "    text = re.sub('<a\\s.*?>', ' HYPERLINK ', text, flags=re.M | re.S | re.I)\n",
    "    text = re.sub('<.*?>', '', text, flags=re.M | re.S)\n",
    "    text = re.sub(r'(\\s*\\n)+', '\\n', text, flags=re.M | re.S)\n",
    "    return unescape(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<HTML><HEAD><TITLE></TITLE><META http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1252\"><STYLE>A:link {TEX-DECORATION: none}A:active {TEXT-DECORATION: none}A:visited {TEXT-DECORATION: none}A:hover {COLOR: #0033ff; TEXT-DECORATION: underline}</STYLE><META content=\"MSHTML 6.00.2713.1100\" name=\"GENERATOR\"></HEAD>\n",
      "<BODY text=\"#000000\" vLink=\"#0033ff\" link=\"#0033ff\" bgColor=\"#CCCC99\"><TABLE borderColor=\"#660000\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\" width=\"100%\"><TR><TD bgColor=\"#CCCC99\" valign=\"top\" colspan=\"2\" height=\"27\">\n",
      "<font size=\"6\" face=\"Arial, Helvetica, sans-serif\" color=\"#660000\">\n",
      "<b>OTC</b></font></TD></TR><TR><TD height=\"2\" bgcolor=\"#6a694f\">\n",
      "<font size=\"5\" face=\"Times New Roman, Times, serif\" color=\"#FFFFFF\">\n",
      "<b>&nbsp;Newsletter</b></font></TD><TD height=\"2\" bgcolor=\"#6a694f\"><div align=\"right\"><font color=\"#FFFFFF\">\n",
      "<b>Discover Tomorrow's Winners&nbsp;</b></font></div></TD></TR><TR><TD height=\"25\" colspan=\"2\" bgcolor=\"#CCCC99\"><table width=\"100%\" border=\"0\"  ...\n"
     ]
    }
   ],
   "source": [
    "html_spam_emails = [email for email in X_train[y_train==1]\n",
    "                    if get_email_structure(email) == \"text/html\"]\n",
    "sample_html_spam = html_spam_emails[7]\n",
    "print(sample_html_spam.get_content().strip()[:1000], \"...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "OTC\n",
      " Newsletter\n",
      "Discover Tomorrow's Winners \n",
      "For Immediate Release\n",
      "Cal-Bay (Stock Symbol: CBYI)\n",
      "Watch for analyst \"Strong Buy Recommendations\" and several advisory newsletters picking CBYI.  CBYI has filed to be traded on the OTCBB, share prices historically INCREASE when companies get listed on this larger trading exchange. CBYI is trading around 25 cents and should skyrocket to $2.66 - $3.25 a share in the near future.\n",
      "Put CBYI on your watch list, acquire a position TODAY.\n",
      "REASONS TO INVEST IN CBYI\n",
      "A profitable company and is on track to beat ALL earnings estimates!\n",
      "One of the FASTEST growing distributors in environmental & safety equipment instruments.\n",
      "Excellent management team, several EXCLUSIVE contracts.  IMPRESSIVE client list including the U.S. Air Force, Anheuser-Busch, Chevron Refining and Mitsubishi Heavy Industries, GE-Energy & Environmental Research.\n",
      "RAPIDLY GROWING INDUSTRY\n",
      "Industry revenues exceed $900 million, estimates indicate that there could be as much as $25 billi ...\n"
     ]
    }
   ],
   "source": [
    "print(html_to_plain_text(sample_html_spam.get_content())[:1000], \"...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "OTC\n",
      " Newsletter\n",
      "Discover Tomorrow's Winners \n",
      "For Immediate Release\n",
      "Cal-Bay (Stock Symbol: CBYI)\n",
      "Wat ...\n"
     ]
    }
   ],
   "source": [
    "# 编写一个函数，它以电子邮件为输入，并以纯文本形式返回其内容，无论其格式是什么\n",
    "def email_to_text(email):\n",
    "    html = None\n",
    "    for part in email.walk():\n",
    "        ctype = part.get_content_type()\n",
    "        if not ctype in (\"text/plain\", \"text/html\"):\n",
    "            continue\n",
    "        try:\n",
    "            content = part.get_content()\n",
    "        except: # 解决编码问题\n",
    "            content = str(part.get_payload())\n",
    "        if ctype == \"text/plain\":\n",
    "            return content\n",
    "        else:\n",
    "            html = content\n",
    "    if html:\n",
    "        return html_to_plain_text(html)\n",
    "    \n",
    "print(email_to_text(sample_html_spam)[:100], \"...\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Computations => comput\n",
      "Computation => comput\n",
      "Computing => comput\n",
      "Computed => comput\n",
      "Compute => comput\n",
      "Compulsive => compuls\n"
     ]
    }
   ],
   "source": [
    "import nltk\n",
    "from urlextract import URLExtract\n",
    "\n",
    "try:\n",
    "    import nltk\n",
    "\n",
    "    stemmer = nltk.PorterStemmer()\n",
    "    for word in (\"Computations\", \"Computation\", \"Computing\", \"Computed\", \"Compute\", \"Compulsive\"):\n",
    "        print(word, \"=>\", stemmer.stem(word))\n",
    "except ImportError:\n",
    "    print(\"Error: stemming requires the NLTK module.\")\n",
    "    stemmer = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.base import BaseEstimator, TransformerMixin\n",
    "\n",
    "class EmailToWordCounterTransformer(BaseEstimator, TransformerMixin):\n",
    "    def __init__(self, strip_headers=True, lower_case=True, remove_punctuation=True,\n",
    "                 replace_urls=True, replace_numbers=True,  stemming=True):\n",
    "        self.strip_headers = strip_headers\n",
    "        self.lower_case = lower_case\n",
    "        self.remove_punctuation = remove_punctuation\n",
    "        self.replace_urls = replace_urls\n",
    "        self.replace_numbers = replace_numbers\n",
    "        self.stemming = stemming\n",
    "    def fit(self, X, y=None):\n",
    "        return self\n",
    "    def transform(self, X, y=None):\n",
    "        X_transformed = []\n",
    "        for email in X:\n",
    "            text = email_to_text(email) or \"\"\n",
    "            if self.lower_case:\n",
    "                text = text.lower()\n",
    "            if self.replace_urls:\n",
    "                extractor = URLExtract()\n",
    "                urls = list(set(extractor.find_urls(text)))\n",
    "                urls.sort(key=lambda url: len(url), reverse=True)\n",
    "                for url in urls:  # 替换url 为 ‘URL’\n",
    "                    text = text.replace(url, \" URL \")\n",
    "            if self.replace_numbers:  # 替换数字\n",
    "                text = re.sub(r'\\d+(?:\\.\\d*(?:[eE]\\d+))?', 'NUMBER', text)\n",
    "            if self.remove_punctuation:  # 删除标点符号\n",
    "                text = re.sub(r'\\W+', ' ', text, flags=re.M)\n",
    "            word_counts = Counter(text.split())\n",
    "            if self.stemming and stemmer is not None:\n",
    "                stemmed_word_counts = Counter()\n",
    "                for word, count in word_counts.items():\n",
    "                    stemmed_word = stemmer.stem(word)\n",
    "                    stemmed_word_counts[stemmed_word] += count\n",
    "                word_counts = stemmed_word_counts\n",
    "            X_transformed.append(word_counts)\n",
    "        return np.array(X_transformed)\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([Counter({'chuck': 1, 'murcko': 1, 'wrote': 1, 'stuff': 1, 'yawn': 1, 'r': 1}),\n",
       "       Counter({'the': 11, 'of': 9, 'and': 8, 'all': 3, 'christian': 3, 'to': 3, 'by': 3, 'jefferson': 2, 'i': 2, 'have': 2, 'superstit': 2, 'one': 2, 'on': 2, 'been': 2, 'ha': 2, 'half': 2, 'rogueri': 2, 'teach': 2, 'jesu': 2, 'some': 1, 'interest': 1, 'quot': 1, 'url': 1, 'thoma': 1, 'examin': 1, 'known': 1, 'word': 1, 'do': 1, 'not': 1, 'find': 1, 'in': 1, 'our': 1, 'particular': 1, 'redeem': 1, 'featur': 1, 'they': 1, 'are': 1, 'alik': 1, 'found': 1, 'fabl': 1, 'mytholog': 1, 'million': 1, 'innoc': 1, 'men': 1, 'women': 1, 'children': 1, 'sinc': 1, 'introduct': 1, 'burnt': 1, 'tortur': 1, 'fine': 1, 'imprison': 1, 'what': 1, 'effect': 1, 'thi': 1, 'coercion': 1, 'make': 1, 'world': 1, 'fool': 1, 'other': 1, 'hypocrit': 1, 'support': 1, 'error': 1, 'over': 1, 'earth': 1, 'six': 1, 'histor': 1, 'american': 1, 'john': 1, 'e': 1, 'remsburg': 1, 'letter': 1, 'william': 1, 'short': 1, 'again': 1, 'becom': 1, 'most': 1, 'pervert': 1, 'system': 1, 'that': 1, 'ever': 1, 'shone': 1, 'man': 1, 'absurd': 1, 'untruth': 1, 'were': 1, 'perpetr': 1, 'upon': 1, 'a': 1, 'larg': 1, 'band': 1, 'dupe': 1, 'import': 1, 'led': 1, 'paul': 1, 'first': 1, 'great': 1, 'corrupt': 1}),\n",
       "       Counter({'url': 4, 's': 3, 'group': 3, 'to': 3, 'in': 2, 'forteana': 2, 'martin': 2, 'an': 2, 'and': 2, 'we': 2, 'is': 2, 'yahoo': 2, 'unsubscrib': 2, 'y': 1, 'adamson': 1, 'wrote': 1, 'for': 1, 'altern': 1, 'rather': 1, 'more': 1, 'factual': 1, 'base': 1, 'rundown': 1, 'on': 1, 'hamza': 1, 'career': 1, 'includ': 1, 'hi': 1, 'belief': 1, 'that': 1, 'all': 1, 'non': 1, 'muslim': 1, 'yemen': 1, 'should': 1, 'be': 1, 'murder': 1, 'outright': 1, 'know': 1, 'how': 1, 'unbias': 1, 'memri': 1, 'don': 1, 't': 1, 'html': 1, 'rob': 1, 'sponsor': 1, 'number': 1, 'dvd': 1, 'free': 1, 'p': 1, 'join': 1, 'now': 1, 'from': 1, 'thi': 1, 'send': 1, 'email': 1, 'egroup': 1, 'com': 1, 'your': 1, 'use': 1, 'of': 1, 'subject': 1})],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_few = X_train[:3]\n",
    "X_few_wordcounts = EmailToWordCounterTransformer().fit_transform(X_few)\n",
    "X_few_wordcounts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.sparse import csr_matrix\n",
    "\n",
    "class WordCounterToVectorTransformer(BaseEstimator, TransformerMixin):\n",
    "    def __init__(self, vocabulary_size = 1000):\n",
    "        self.vocabulary_size = vocabulary_size  # 词汇量\n",
    "    def fit(self, X, y = None):\n",
    "        total_count = Counter()\n",
    "        for word_count in X:\n",
    "            for word, count in word_count.items():\n",
    "                total_count[word] += min(count, 10)\n",
    "        most_common = total_count.most_common()[:self.vocabulary_size]\n",
    "        self.most_common_ = most_common\n",
    "        self.vocabulary_ = {word: index + 1 for index, (word, count) in enumerate(most_common)}\n",
    "        return self\n",
    "    def transform(self, X, y = None):\n",
    "        rows = []\n",
    "        cols = []\n",
    "        data = []\n",
    "        for row, word_count in enumerate(X):\n",
    "            for word, count in word_count.items():\n",
    "                rows.append(row) # 训练集 实例个数\n",
    "                cols.append(self.vocabulary_.get(word, 0)) # 取得单词在词汇表中的索引位置，0代表未出现在词汇表中\n",
    "                data.append(count)\n",
    "        return csr_matrix((data, (rows, cols)), shape=(len(X), self.vocabulary_size + 1)) # 输出稀疏矩阵 +1因为第一列要显示未出现在词汇表中的单词统计数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  (0, 0)\t1\n",
      "  (0, 1)\t0\n",
      "  (0, 2)\t1\n",
      "  (1, 0)\t0\n",
      "  (1, 1)\t1\n",
      "  (1, 2)\t1\n",
      "  (2, 0)\t1\n",
      "  (2, 1)\t1\n",
      "  (2, 2)\t0\n",
      "[[1 0 1]\n",
      " [0 1 1]\n",
      " [1 1 0]]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 1],\n",
       "       [0, 1, 1],\n",
       "       [1, 1, 0]], dtype=int32)"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from scipy.sparse import *\n",
    " \n",
    "row =  [0,0,0,1,1,1,2,2,2]#行指标\n",
    "col =  [0,1,2,0,1,2,0,1,2]#列指标\n",
    "data = [1,0,1,0,1,1,1,1,0]#在行指标列指标下的数字\n",
    "team = csr_matrix((data,(row,col)),shape=(3,3))\n",
    "print(team)\n",
    "print(team.todense())\n",
    "team.toarray()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 11)"
      ]
     },
     "execution_count": 125,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vocab_transformer = WordCounterToVectorTransformer(vocabulary_size=10)\n",
    "X_few_vectors = vocab_transformer.fit_transform(X_few_wordcounts)\n",
    "X_few_vectors.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0],\n",
       "       [99, 11,  9,  8,  3,  1,  3,  1,  3,  2,  3],\n",
       "       [67,  0,  1,  2,  3,  4,  1,  2,  0,  1,  0]], dtype=int32)"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_few_vectors.toarray()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'the': 1,\n",
       " 'of': 2,\n",
       " 'and': 3,\n",
       " 'to': 4,\n",
       " 'url': 5,\n",
       " 'all': 6,\n",
       " 'in': 7,\n",
       " 'christian': 8,\n",
       " 'on': 9,\n",
       " 'by': 10}"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vocab_transformer.vocabulary_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.pipeline import Pipeline\n",
    "\n",
    "preprocess_pipeline = Pipeline([\n",
    "    (\"email_to_wordcount\", EmailToWordCounterTransformer()),\n",
    "    (\"wordcount_to_vector\", WordCounterToVectorTransformer()),\n",
    "])\n",
    "\n",
    "X_train_transformed = preprocess_pipeline.fit_transform(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[CV]  ................................................................\n",
      "[CV] .................................. , score=0.98125, total=   0.0s\n",
      "[CV]  ................................................................\n",
      "[CV] .................................. , score=0.98375, total=   0.0s\n",
      "[CV]  ................................................................\n",
      "[CV] .................................. , score=0.99125, total=   0.0s\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[Parallel(n_jobs=1)]: Done   1 out of   1 | elapsed:    0.0s remaining:    0.0s\n",
      "[Parallel(n_jobs=1)]: Done   2 out of   2 | elapsed:    0.0s remaining:    0.0s\n",
      "[Parallel(n_jobs=1)]: Done   3 out of   3 | elapsed:    0.2s finished\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.9854166666666666"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.model_selection import cross_val_score\n",
    "\n",
    "log_clf = LogisticRegression(solver=\"liblinear\", random_state=42) # 采用逻辑回归分类器\n",
    "score = cross_val_score(log_clf, X_train_transformed, y_train, cv=3, verbose=3)\n",
    "score.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "精度: 96.88%\n",
      "召回: 97.89%\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import precision_score, recall_score\n",
    "\n",
    "X_test_transformed = preprocess_pipeline.transform(X_test)\n",
    "\n",
    "log_clf = LogisticRegression(solver=\"liblinear\", random_state=42)\n",
    "log_clf.fit(X_train_transformed, y_train)\n",
    "\n",
    "y_pred = log_clf.predict(X_test_transformed)\n",
    "\n",
    "print(\"精度: {:.2f}%\".format(100 * precision_score(y_test, y_pred)))\n",
    "print(\"召回: {:.2f}%\".format(100 * recall_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 为MNIST数据集构建一个分类器，并在测试集上达成超过90%的精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.datasets import fetch_mldata\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "import numpy as np\n",
    "\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {},
   "outputs": [],
   "source": [
    "mnist = fetch_mldata('MNIST original', data_home='./')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {},
   "outputs": [],
   "source": [
    "X, y = mnist[\"data\"], mnist[\"target\"]\n",
    "X_train, y_train = X[:60000], y[:60000]\n",
    "shuffle_index = np.random.permutation(60000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_traina, y_traina = X_train[shuffle_index], y_train[shuffle_index]\n",
    "X_train, y_train = X_traina[:50000], y_traina[:50000]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [],
   "source": [
    "t1 = time.time()\n",
    "X_test, y_test = X[60000:], y[60000:]\n",
    "\n",
    "\n",
    "param_grid = [{'n_neighbors':[3,4,5], 'weights':['uniform', 'distance']}]\n",
    "knn_clf = KNeighborsClassifier()\n",
    "#knn_clf = KNeighborsClassifier(n_neighbors=3,weights='distance')\n",
    "grid_search = GridSearchCV(knn_clf, param_grid, cv=3, scoring='accuracy', n_jobs=4, verbose=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "11 {0: 4905, 1: 5650, 2: 5002, 3: 5096, 4: 4884, 5: 4477, 6: 4898, 7: 5219, 8: 4870, 9: 4999}\n",
      "Fitting 3 folds for each of 6 candidates, totalling 18 fits\n"
     ]
    }
   ],
   "source": [
    "ret_dict1={0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0}\n",
    "for i in range(len(y_train)):\n",
    "    ret_dict1[int(y_train[i])] += 1\n",
    "\n",
    "print(11, ret_dict1)\n",
    "\n",
    "t2 = time.time()\n",
    "#knn_clf.fit(X_train, y_train)\n",
    "grid_search.fit(X_train, y_train)\n",
    "t3 = time.time()\n",
    "print('train over.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = grid_search.predict(X_test)\n",
    "ret_dict2={0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0}\n",
    "t4 = time.time()\n",
    "\n",
    "for i in range(len(y_pred)):\n",
    "    ret_dict2[int(y_pred[i])] += 1\n",
    "        \n",
    "print(22, ret_dict2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import precision_score, recall_score,confusion_matrix\n",
    "cm = confusion_matrix(y_test, y_pred)\n",
    "print('\\ncm=', cm)\n",
    "ps = precision_score(y_test, y_pred, average=None)\n",
    "print('\\nps=', ps, np.average(ps))\n",
    "rs = recall_score(y_test, y_pred, average=None)\n",
    "print('\\nrs=', rs, np.average(rs))\n",
    "para = grid_search.best_params_\n",
    "print('\\nBest para:', para)\n",
    "t5 = time.time()\n",
    "\n",
    "print('Time cost:')\n",
    "print('    Preprocess:', t2-t1)\n",
    "print('    Train:', t3-t2)\n",
    "print('    Predict:', t4-t3)\n",
    "print('    Calc accu:', t5-t4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
